package com.colter.project.sample.thread.part03.test1;

import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;

//并发中的阶段切换  Phaser
public class Test6 {
	public static void main(String[] args) {
		Thread[] threads = new Thread[5];
		Phaser phaser = new MyPhaser();

		for (int i = 0; i < threads.length; i++) {
			Student s = new Student(phaser);
			phaser.register();
			threads[i] = new Thread(s);
			threads[i].start();
		}

		for (int i = 0; i < threads.length; i++) {
			try {
				threads[i].join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		System.out.println("Terminated:" + phaser.isTerminated());
	}

}

class MyPhaser extends Phaser {

	@Override
	protected boolean onAdvance(int phase, int registeredParties) {
		switch (phase) {
		case 0:
			return studentArrive();
		case 1:
			return finishExercise1();
		case 2:
			return finishExercise2();
		case 3:
			return finishExam();
		default:
			return false;
		}
	}

	private boolean studentArrive() {
		System.out.println("Exam are going to start.Students are ready.");
		System.out.println("We have " + getRegisteredParties() + " students");
		return false;
	}

	private boolean finishExercise1() {
		System.out.println("Finished Exercise1.");
		System.out.println("It is time to sencond.");
		return false;
	}

	private boolean finishExercise2() {
		System.out.println("Finished Exercise2.");
		System.out.println("It is time to third.");
		return false;
	}

	private boolean finishExam() {
		System.out.println("Finished Exam.");
		System.out.println("Thank you for your time.");
		return true;
	}
}

class Student implements Runnable {
	private Phaser phaser;

	public Student(Phaser phaser) {
		super();
		this.phaser = phaser;
	}

	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName() + " arrived to do the exam.");
		phaser.arriveAndAwaitAdvance();

		System.out.println(Thread.currentThread().getName() + " going to do exercise 1.");
		doExercise1();
		System.out.println(Thread.currentThread().getName() + " finished exercise 1.");
		phaser.arriveAndAwaitAdvance();

		System.out.println(Thread.currentThread().getName() + " going to do exercise 2.");
		doExercise2();
		System.out.println(Thread.currentThread().getName() + " finished exercise 2.");
		phaser.arriveAndAwaitAdvance();

		System.out.println(Thread.currentThread().getName() + " going to do exercise 3.");
		doExercise3();
		System.out.println(Thread.currentThread().getName() + " finished exam.");
		phaser.arriveAndDeregister();

	}

	private void doExercise1() {
		long duration = (long) (Math.random() * 10);
		try {
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	private void doExercise2() {
		long duration = (long) (Math.random() * 10);
		try {
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	private void doExercise3() {
		long duration = (long) (Math.random() * 10);
		try {
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}
